package spc.webos.queue.ibmmq;

import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;

import spc.webos.queue.AbstractCnnPool;
import spc.webos.util.JsonUtil;
import spc.webos.util.StringX;

public class MQCnnPool extends AbstractCnnPool {
	protected boolean cnnOnBorrow;
	long no;
	public static final String SHORTCNN_KEY = "shortCnn";
	public static final String APPCD_KEY = "appCd";
	public static final String NODE_KEY = "node";
	public static final String MAXCNN_KEY = "maxCnnNum";
	public static final String REQQNM_KEY = "reqQName";
	public static final String TIMEOUT_KEY = "timeout";
	public static final String EXPIRY_KEY = "expirySeconds";
	public static final String CNNHOLDTIME_KEY = "cnnHoldTime";
	public static final String CNNIDLETIME_KEY = "cnnIdleTime";
	public static final String KEEPQUEUE_KEY = "keepQueue";
	public static final String BORROWONINIT_KEY = "borrowOnInit";

	public MQCnnPool() {
		this.autoIncrease = true;
		this.borrowOnInit = true;
	}

	public MQCnnPool(int max, Hashtable props) {
		this.max = max;
		this.props = props;
		this.autoIncrease = true;
		this.borrowOnInit = true;
	}

	public MQCnnPool(int max, Hashtable props, int cnnHoldTime) {
		this.max = max;
		this.props = props;
		this.cnnHoldTime = cnnHoldTime;
		this.autoIncrease = true;
		this.borrowOnInit = true;
	}

	public MQCnnPool(int max, Hashtable props, int cnnHoldTime, int cnnIdleTime) {
		this.max = max;
		this.props = props;
		this.cnnHoldTime = cnnHoldTime;
		this.cnnIdleTime = cnnIdleTime;
		this.autoIncrease = true;
		this.borrowOnInit = true;
	}

	public MQCnnPool(int max, Hashtable props, int cnnHoldTime,
			int cnnIdleTime, boolean autoIncrease) {
		this.max = max;
		this.props = props;
		this.cnnHoldTime = cnnHoldTime;
		this.cnnIdleTime = cnnIdleTime;
		this.autoIncrease = autoIncrease;
		this.borrowOnInit = true;
	}

	public MQCnnPool(int max, Hashtable props, int cnnHoldTime,
			int cnnIdleTime, boolean autoIncrease, long waitTime) {
		this.max = max;
		this.props = props;
		this.cnnHoldTime = cnnHoldTime;
		this.cnnIdleTime = cnnIdleTime;
		this.autoIncrease = autoIncrease;
		this.waitTime = waitTime;
		this.borrowOnInit = true;
	}

	public void init() throws Exception {
		Object ccsid = this.props.get("CCSID");
		if (ccsid instanceof String)
			this.props.put("CCSID", new Integer((String) ccsid));
		Object port = this.props.get("port");
		if (port instanceof String) {
			this.props.put("port", new Integer((String) port));
		}
		if (!this.props.containsKey("channel")) {
			this.props.put("channel", MQManager.SYS_DEF_CHL);
		}

		if (!this.props.containsKey("channel")) {
			this.props.put("channel", MQManager.SYS_DEF_CHL);
		}

		try {
			super.init();
		} catch (Exception e) {
			this.log.error("MQCnnPool init: " + this.props, e);
		}
	}

	public Object newIntance() {
		String name = this.name + "_" + this.no++;
		if (this.log.isInfoEnabled())
			this.log.info("new mqm: " + this.props + ", keep: "
					+ this.keepQueue + "," + this.cnnOnBorrow + "," + name);
		MQManager qm = new MQManager(this.props, this.cnnHoldTime,
				this.cnnIdleTime, this.keepQueue);
		qm.name = name;
		try {
			if (this.cnnOnBorrow)
				qm.connect(1);
		} catch (Exception e) {
			this.log.warn("fail to MQ cnn:" + this.props + ", " + e);
		}
		return qm;
	}

	public boolean release(Object obj) {
		MQManager mq = (MQManager) obj;
		if (!super.release(mq))
			mq.disconnect();
		return true;
	}

	public synchronized void destory() {
		if (this.log.isInfoEnabled())
			this.log.info("destroy MQ pool(" + this.name + ") : "
					+ this.pool.size());
		for (int i = 0; i < this.pool.size(); ++i)
			((MQManager) this.pool.get(i)).disconnect();
		this.pool.clear();
	}

	public static MQCnnPool createChl(String chl) throws Exception {
		return createChl((Map) JsonUtil.json2obj(chl));
	}

	public static MQCnnPool createChl(Map channel) throws Exception {
		MQCnnPool cnnpool = new MQCnnPool();
		String maxCnnNum = StringX.null2emptystr(channel.get("maxCnnNum"));
		String cnnHoldTime = StringX.null2emptystr(channel.get("cnnHoldTime"));
		String cnnIdleTime = StringX.null2emptystr(channel.get("cnnIdleTime"));
		String keepQueue = StringX.null2emptystr(channel.get("keepQueue"));
		String name = StringX.null2emptystr(channel.get("name"));
		if (!StringX.nullity(name)) {
			cnnpool.setName(name);
		}
		if (!StringX.nullity(maxCnnNum))
			cnnpool.setMax(Integer.parseInt(maxCnnNum));
		else
			cnnpool.setMax(1);
		if (!StringX.nullity(cnnHoldTime))
			cnnpool.setCnnHoldTime(Integer.parseInt(cnnHoldTime));
		if (!StringX.nullity(cnnIdleTime))
			cnnpool.setCnnIdleTime(Integer.parseInt(cnnIdleTime));
		if (!StringX.nullity(keepQueue)) {
			cnnpool.setKeepQueue(Boolean.TRUE.toString().equalsIgnoreCase(
					keepQueue));
		}
		Object p = channel.get("channel");
		if (p instanceof Map)
			cnnpool.setProps(new Hashtable((Map) p));
		else {
			cnnpool.setProps(MQManager.str2map(p.toString()));
		}
		cnnpool.setBorrowOnInit(false);
		cnnpool.init();
		return cnnpool;
	}

	public static List<MQCnnPool> createChlList(String chl) throws Exception {
		List channels = (List) JsonUtil.json2obj(chl);
		List cnnpools = new ArrayList();
		for (int i = 0; i < channels.size(); ++i)
			cnnpools.add(createChl((Map) channels.get(i)));
		return cnnpools;
	}

	public boolean isCnnOnBorrow() {
		return this.cnnOnBorrow;
	}

	public void setCnnOnBorrow(boolean cnnOnBorrow) {
		this.cnnOnBorrow = cnnOnBorrow;
	}
}
